/**
 * 封装一些常用的方法
 * */

// 控制promise并发的函数
export const concurrencyRequest = (promiseArr,maxNum) => {
  return new Promise((resolve,reject) => {
    if(promiseArr.length === 0){
      resolve([]);
      return;
    }
    const results = [];
    let index = 0; // 下一个请求的下标
    let count = 0; // 当前请求完成的数量
    let rejectLock = false; // 出现错误时的锁
    async function request(){
      if(index === promiseArr.length || rejectLock){
        return;
      }
      const i = index; // 保存序号，使result和promiseArr相对应
      const {func,args} = promiseArr[index];
      index++;
      try{
        results[i] = await func(...args);
      }catch(err){
        rejectLock = true;
        reject();
      }finally{
        count++;
        // 判断是否所有的请求都已完成
        if(count === promiseArr.length){
          resolve(results);
        }
        request();
      }
    }
    // maxNum和promiseArr.length取最小进行调用
    const times = Math.min(maxNum,promiseArr.length);
    for(let i = 0; i < times; i++){
      request();
    }
  });
};
// 生成uuid
export const genUuid = () => {
  const NUM1 = 16;
  const NUM2 = 0x3;
  const NUM3 = 0x8;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){
    const r = (Math.random() * NUM1) | 0,v = c === 'x'?r:(r & NUM2) | NUM3;
    return v.toString(NUM1);
  });
};
// 原生的下载文件操作
export const getDataByUrl = (url,type) => {
  return new Promise((resolve,reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET',url);
    xhr.responseType = type
    xhr.onload = () => {
      resolve(xhr.response);
    };
    xhr.onerror = e => {
      reject(e);
    };
    xhr.send();
  });
};
// 防抖函数
export const debounce = (fn,delay) => {
  let timer = null;
  return function(...args){
    if(timer){
      clearTimeout(timer);
      timer = setTimeout(() => {
        fn(...args);
      },delay);
    }else{
      timer = setTimeout(() => {
        fn(...args);
      },delay);
    }
  };
};
// 节流函数
export const throttle = (fn,delay) => {
  let valid = true;
  return function(...args){
    if(!valid){
      return false;
    }
    valid = false; //防止他人执行
    fn(...args); // 直接执行函数
    setTimeout(() => {
      valid = true; // 延迟时间过后打开锁
    },delay);
  };
};
// t深拷贝合并对象的方法，并能触发监听
import _mergeWith from 'lodash/mergeWith';
// 拷贝对象
export function extendObject(...args){
  const {length} = args;// 仿写extendObject方法
  let i = 1;
  const newArguments = [];
  let deep = false;// 是否深拷贝
  let target = args[0];// 合并目标对象
  if(typeof target === 'boolean'){// 第一个值为布尔值代表是否深拷贝
    deep = target;
    target = args[1] || {};
    i = 2;
  }
  if(typeof target !== 'object' && typeof target !== 'function'){// 兼容处理
    target = {};
  }
  if(length === i){// 如果只有一个对象，直接返回
    return target;
  }
  // 给予一个新的接受参数的对象
  for(i; i < length; i += 1){
    newArguments.push(args[i]);
  }
  if(deep){// 深浅拷贝的不同处理
    _mergeWith(target,...newArguments,(objValue,srcValue,key,object) => {// 需要动态监听必须深拷贝一次该对象
      if(target.filterCopyKey && target.filterCopyKey.includes(key)){
        return srcValue;
      }
      if(!Object.keys(object).includes(key)){// 如果没有该key值，则强行使用set创建该key值的监听
        Vue.set(object,key);
      }
    });
  }else{
    target = Object.assign({},target,...newArguments);// 不用深拷贝直接使用Object.assign
  }
  return target;
}
// 复制到剪切板
export function copyText(text){
  const textarea = document.createElement('textarea');
  textarea.style.fontSize = '12pt';// Prevent zooming on iOS
  textarea.style.border = '0'; // Reset box model
  textarea.style.padding = '0';
  textarea.style.margin = '0';
  textarea.style.position = 'absolute';// Move element out of screen horizontally
  textarea.style.left = '-9999px';
  const yPosition = window.pageYOffset || document.documentElement.scrollTop;// Move element to the same position vertically
  textarea.style.top = `${yPosition}px`;
  textarea.setAttribute('readonly','');
  textarea.value = text;
  document.body.appendChild(textarea);
  textarea.select();
  textarea.setSelectionRange(0,textarea.value.length);
  let succeeded;
  try{
    succeeded = document.execCommand('copy');
  }catch(err){
    succeeded = false;
  }
  return succeeded;
}
